package com.kede.api.stand.service.impl;

import cn.hutool.core.net.URLDecoder;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.kede.api.ienum.AppIdTypeEnum;
import com.kede.api.stand.domain.WeixTokenDomain;
import com.kede.api.stand.pub.ConstKey;
import com.kede.api.stand.service.LoginService;
import com.kede.api.stand.service.WeixTokenService;
import com.kede.api.stand.utils.GaoDeMapUtil;
import com.kede.domain.OperatUserDomain;
import com.kede.domain.UsersDomain;
import com.kede.pojo.ResHttp;
import com.kede.service.OperatUserService;
import com.kede.service.UsersService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.Map;

/***
 ** @Author:Pr.li
 ** @Description:
 ** @Date: create in 2023/3/31 15:26
 ***/
@Service
@Slf4j
public class LoginServiceImpl implements LoginService {

    @Resource
    private WeixTokenService weixTokenService;

    @Resource
    private UsersService usersService;

    @Resource
    private OperatUserService operatUserService;

    @Value("${spring.profiles.active}")
    private String env;


    @Override
    public String getToken(AppIdTypeEnum appIdTypeEnum){
        LambdaQueryWrapper<WeixTokenDomain> queryWrapper = new LambdaQueryWrapper<>();
        LocalDateTime now = LocalDateTime.now();
        queryWrapper.eq(WeixTokenDomain::getType,appIdTypeEnum.getType());
        WeixTokenDomain one = weixTokenService.getOne(queryWrapper);

        if (one == null){
            //更新token；
            TokenEntity tokenEntity = doGetToken(appIdTypeEnum);
            WeixTokenDomain weixTokenDomain = new WeixTokenDomain();
            weixTokenDomain.setToken(tokenEntity.getAccess_token());
            weixTokenDomain.setCreateTime(now);
            weixTokenDomain.setUpdateTime(now);
            weixTokenDomain.setType(appIdTypeEnum.getType());
            weixTokenDomain.setTime(tokenEntity.getTime());
            weixTokenService.save(weixTokenDomain);
            return tokenEntity.getAccess_token();
        }else if(one.getTime().isBefore(now)){
//            过期了
            TokenEntity tokenEntity = doGetToken(appIdTypeEnum);
            one.setToken(tokenEntity.getAccess_token());
            one.setTime(tokenEntity.getTime());
            one.setUpdateTime(now);
            weixTokenService.updateById(one);
            return tokenEntity.getAccess_token();
        }else {
            return one.getToken();
        }
    }

    public TokenEntity doGetToken(AppIdTypeEnum appIdTypeEnum){
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential");
        stringBuilder.append("&appid=");
        stringBuilder.append(appIdTypeEnum.getAppid());
        stringBuilder.append("&secret=");
        stringBuilder.append(appIdTypeEnum.getAppSecret());
        String s = HttpUtil.get(stringBuilder.toString());
        TokenEntity tokenEntity = JSONObject.parseObject(s, TokenEntity.class);
        tokenEntity.setTime(LocalDateTime.now().plusSeconds(7000));
        return tokenEntity;
    }

    /**
     * {
     *     "errcode":0,
     *     "errmsg":"ok",
     *     "phone_info": {
     *         "phoneNumber":"xxxxxx",
     *         "purePhoneNumber": "xxxxxx",
     *         "countryCode": 86,
     *         "watermark": {
     *             "timestamp": 1637744274,
     *             "appid": "xxxx"
     *         }
     *     }
     * }
     * @param code
     * @param appIdTypeEnum
     * @return
     */
    @Override
    public String getWxPhone(String code,AppIdTypeEnum appIdTypeEnum){

        if (!env.equals("prod")){
            String phone =999 +RandomUtil.randomNumbers(8);
            return "{\"errcode\":0,\"errmsg\":\"ok\",\"phone_info\": {\"phoneNumber\":\"xxxxxx\",\"purePhoneNumber\": \""+phone+"\",\"countryCode\": 86,\"watermark\": {\"timestamp\": 1637744274,\"appid\": \"xxxx\"}}}";
        }
        String url ="https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+this.getToken(appIdTypeEnum);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code",code);
        HttpRequest post1 = HttpUtil.createPost(url);
        post1.body(jsonObject.toJSONString(),"application/json");
        String body = post1.execute().body();
        log.debug("获取手机号的post 返回结果=={}",body);
        return body;
    }


    //给小程序绑定手机号
    @Override
    public ResHttp bindPhoneByOpenid(String phone,String openid,String avatarUrl,String nickName,
                                     AppIdTypeEnum appIdTypeEnum,String lng,String lat,String scene){
        LambdaQueryWrapper<UsersDomain> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UsersDomain::getUserType,appIdTypeEnum.getPhpType());
        queryWrapper.eq(UsersDomain::getUsersPhone,phone);
        UsersDomain one = usersService.getOne(queryWrapper);
        if(one==null){
            //新用户
            UsersDomain usersDomain = new UsersDomain();
            setUserOpenidByAppidType(usersDomain,openid,appIdTypeEnum);
            usersDomain.setUsersName(nickName);
            usersDomain.setUsersPhone(phone);
            usersDomain.setUsersImage(avatarUrl);
            usersDomain.setUserType(appIdTypeEnum.getPhpType());
            Long l = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
            int time = Integer.valueOf(l.toString());
            usersDomain.setCreatetime(time);
            GaoDeMapUtil.AddressComponentDto addressComponentByLocation = null;
            try{
                addressComponentByLocation = GaoDeMapUtil.getAddressComponentByLocation(lng, lat);
                usersDomain.setAddress(addressComponentByLocation.getAdcode());
            }catch (Exception e){
                //不做处理
            }
            boolean b = usersService.save(usersDomain);
            String senceNo = getMapByUrlParam(scene).get(ConstKey._SenceNO);
            if(StrUtil.isNotBlank(senceNo)){
                OperatUserDomain operatUserDomain = new OperatUserDomain();
                operatUserDomain.setUserId(usersDomain.getId());
                operatUserDomain.setCreateTime(LocalDateTime.now());
                operatUserDomain.setUserPhone(phone);
                if(addressComponentByLocation!=null){
                    operatUserDomain.setAdcode(addressComponentByLocation.getAdcode());
                }
                operatUserDomain.setSenceNo(senceNo);
                operatUserService.save(operatUserDomain);
            }
            return b ? ResHttp.okData(usersDomain) : ResHttp.fail();
        }else {
            setUserOpenidByAppidType(one,openid,appIdTypeEnum);
            usersService.updateById(one);
            return ResHttp.okData(one);
        }

    }

    /**
     * 解析url地址传过来的参数
     * @param originalStr
     * @return
     */
    public static Map<String,String> getMapByUrlParam(String originalStr){
        Map<String,String> paramMap = new HashMap<>();
        if(StrUtil.isBlank(originalStr)){
            return paramMap;
        }
        try {
            String paramStr = URLDecoder.decode(originalStr, CharsetUtil.CHARSET_UTF_8);
            String[] paramArr = paramStr.split("&");
            for (String qMap : paramArr) {
                String[] query = qMap.split("=");
                if(query.length == 2){
                    paramMap.put(query[0],query[1]);
                }
            }
        }catch (Exception e){

        }
        return paramMap;
    }

    public UsersDomain  getOneByOpenid(String openid,AppIdTypeEnum appIdTypeEnum){
        LambdaQueryWrapper<UsersDomain> queryWrapper = new LambdaQueryWrapper<>();
        switch (appIdTypeEnum){
            case USER_XCX:
                queryWrapper.eq(UsersDomain::getXcxOpenid,openid);
                break;
            case QUDAI_XCX:
                queryWrapper.eq(UsersDomain::getXcxQuOpenid,openid);
                break;
            case QISHOU_XCX:
                queryWrapper.eq(UsersDomain::getXcxRiderOpenid,openid);
                break;
            case SHIDAI_XCX:
                queryWrapper.eq(UsersDomain::getXcxShiOpenid,openid);
                break;
            case MENDIAN_XCX:
                queryWrapper.eq(UsersDomain::getXcxStoreOpenid,openid);
                break;
        }
        UsersDomain one = usersService.getOne(queryWrapper);
        return one;
    }
    /**
     * @param jsCode 获取
     * @param appIdTypeEnum
     * @return
     */
    @Override
    public ResHttp doXcxLogin(String jsCode, String nickName, String avatarUrl, AppIdTypeEnum appIdTypeEnum){
        log.debug("appIdTypeEnum=={}",appIdTypeEnum);
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("https://api.weixin.qq.com/sns/jscode2session?");
        stringBuilder.append("appid=").append(appIdTypeEnum.getAppid());
        stringBuilder.append("&secret=").append(appIdTypeEnum.getAppSecret());
        stringBuilder.append("&js_code=").append(jsCode);
        stringBuilder.append("&grant_type=").append("authorization_code");
        String s = HttpUtil.get(stringBuilder.toString());
        XcxLoginEntity xcxLoginEntity = JSONObject.parseObject(s, XcxLoginEntity.class);
        log.debug("微信登录返回=={}",s);
        log.debug("XcxLoginEntityd的转换结果{}",xcxLoginEntity);
        if(StringUtils.hasText(xcxLoginEntity.getOpenid())){
            UsersDomain one = this.getOneByOpenid(xcxLoginEntity.getOpenid(),appIdTypeEnum);
            Map<String,String> data = new HashMap<>();
            if (one==null){
                //新用户
                log.debug("新用户 -99");
                data.put("openid",xcxLoginEntity.getOpenid());
                return ResHttp.set(-99,"用户需要绑定手机号",data);
            }else {
                    log.debug("正常登录");
                    return ResHttp.okData(one);
            }
        }else {
            log.debug("小程序微信登录出现错误");
            return ResHttp.failMsg("小程序微信登录出现错误");
        }
    }

    private void setUserOpenidByAppidType(UsersDomain usersDomain,String openid, AppIdTypeEnum appIdTypeEnum){
        switch (appIdTypeEnum){
            case USER_XCX:
                usersDomain.setXcxOpenid(openid);
                break;
            case QUDAI_XCX:
                usersDomain.setXcxQuOpenid(openid);
                break;
            case QISHOU_XCX:
                usersDomain.setXcxRiderOpenid(openid);
                break;
            case SHIDAI_XCX:
                usersDomain.setXcxShiOpenid(openid);
                break;
            case MENDIAN_XCX:
                usersDomain.setXcxStoreOpenid(openid);
                break;
        }
    }

    @Data
    public static class TokenEntity{
        private String access_token;
        private Integer expires_in;
        private LocalDateTime time;
    }

    /**
     * 小程序登录返回的实体
     */
    @Data
    private static class XcxLoginEntity{
        private String session_key;
        private String unionid;
        private String errmsg;
        private String openid;
        private String errcode;
    }

}
